import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Iterator;
import java.util.Vector;

class Base
{
    int x, y; //坐标
    int vx, vy; //移动速度
    String name;
    int type;
    Color color;

    Base(int x, int y, int vx, int vy, String name, int type,
         Color color)
    {
        this.x = x;
        this.y = y;
        this.vx = vx;
        this.vy = vy;
        this.name = name;
        this.type = type;
        this.color = color;
    }
}

class PlaneSelf extends Base
{
    int fireType;
    int fireInterval;
    PlaneSelf(int x, int y, int vx, int vy, String name, int type, int fireType, int fireInterval, Color color) {
        super(x, y, vx, vy, name, type, color);
        this.fireType = fireType;
        this.fireInterval = fireInterval;
    }

    void fire(Vector<BulletSelf> BulletSelfs)
    {
        switch (fireType)
        {
            case 1:
                BulletSelfs.add(new BulletSelf(x, y, -3, -12, "BulletSelf" + "1", type, color));
                BulletSelfs.add(new BulletSelf(x, y, 0, -12, "BulletSelf" + "2", type, color));
                BulletSelfs.add(new BulletSelf(x, y, 3, -12, "BulletSelf" + "3", type, color));
                break;

            case 2:
                BulletSelfs.add(new BulletSelf(x - 80, y, 0, -12, name + "1", type, color));
                BulletSelfs.add(new BulletSelf(x, y, 0, -12, name + "2", type, color));
                BulletSelfs.add(new BulletSelf(x + 80, y, 0, -12, name + "3", type, color));
                break;

            case 3:
                BulletSelfs.add(new BulletSelf(x, y, 0, 2 * vy, name + "1", type, color));
                break;
        }
    }

    void moveRight() {
        this.x += vx;
    }

    void moveLeft() {
        this.x -= vx;
    }

    void moveUp() {
        this.y -= vy;
    }

    void moveDown() {
        this.y += vy;
    }
}

class BulletSelf extends Base
{
    BulletSelf(int x, int y, int vx, int vy, String name, int type, Color color)
    {
        super(x, y, vx, vy, name, type, color);
    }

    void move() {
        this.x += vx;
        this.y += vy;
    }
}

public  class GameFrameSelf extends JFrame {
    static Graphics graphics;
    private final Image buffer;  // 双缓冲图像
    private final Graphics bufferGraphics;  // 双缓冲图像的绘图上下文
    static Vector<PlaneSelf> friendPlaneSelfs;
    static Vector<PlaneSelf> enemyPlaneSelfs;
    static int enemyAddInterval;
    static int enemyCount;
    static Vector<BulletSelf> friendBulletSelfs;
    static Vector<BulletSelf> enemyBulletSelfs;
    int timer;

    static {
        friendPlaneSelfs = new Vector<>();
        enemyPlaneSelfs = new Vector<>();
        friendBulletSelfs = new Vector<>();
        enemyBulletSelfs = new Vector<>();
        enemyAddInterval = 18;
    }

    GameFrameSelf() {
        setLayout(null);
        setSize(700, 900);
        setLocationRelativeTo(null);
        setVisible(true);
        graphics = getContentPane().getGraphics();
        buffer = createImage(700, 900);
        bufferGraphics = buffer.getGraphics();
        bufferGraphics.setFont(new Font("", Font.BOLD, 18));
        friendPlaneSelfs.add(new PlaneSelf(150, 800, 10, 10, "friend1", 1, 1, 7, new Color(0,0,255)));
        friendPlaneSelfs.add(new PlaneSelf(450, 800, 10, 10, "friend2", 1, 2, 5, new Color(0,255,0)));

        addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                PlaneSelf player2 = friendPlaneSelfs.get(1);
                switch (e.getKeyCode()) {
                    case KeyEvent.VK_UP:
                        player2.moveUp();
                        break;
                    case KeyEvent.VK_DOWN:
                        player2.moveDown();
                        break;
                    case KeyEvent.VK_RIGHT:
                        player2.moveRight();
                        break;
                    case KeyEvent.VK_LEFT:
                        player2.moveLeft();
                        break;
                }
            }
        });
        addMouseListener(new MouseListener() {
            @Override
            public void mouseClicked(MouseEvent e) {
                Point mousePoint = e.getPoint();
                PlaneSelf player1 = friendPlaneSelfs.get(0);
                if (mousePoint.x > player1.x)
                    player1.moveRight();
                else
                    player1.moveLeft();

                if (mousePoint.y > player1.y)
                    player1.moveDown();
                else
                    player1.moveUp();
            }

            @Override
            public void mousePressed(MouseEvent e)  {}

            @Override
            public void mouseReleased(MouseEvent e)  {}

            @Override
            public void mouseEntered(MouseEvent e)  {}

            @Override
            public void mouseExited(MouseEvent e) {}
        });
    }

    void BulletSelfsOperation(Vector<BulletSelf> BulletSelfs, Graphics graphics)
    {
        Iterator<BulletSelf> iterator = BulletSelfs.iterator();
        while (iterator.hasNext())
        {
            BulletSelf BulletSelf = iterator.next();
            graphics.setColor(BulletSelf.color);
            graphics.drawString(BulletSelf.name, BulletSelf.x, BulletSelf.y); //画子弹
            BulletSelf.move(); //子弹要移动，并且是自动移动，而飞机是通过方向键移动的

            //如果子弹超出窗口的边界，就要把子弹删除
            if (BulletSelf.x < 0 || BulletSelf.x > 700 || BulletSelf.y < 0 || BulletSelf.y > 900)
                iterator.remove();
        }
    }

    void hit(Vector<PlaneSelf> PlaneSelfs, Vector<BulletSelf> BulletSelfs)
    {
        Iterator<BulletSelf> iteratorBulletSelf = BulletSelfs.iterator();
        while (iteratorBulletSelf.hasNext())
        {
            BulletSelf BulletSelf = iteratorBulletSelf.next();

            Iterator<PlaneSelf> iteratorPlaneSelf = PlaneSelfs.iterator();
            while (iteratorPlaneSelf.hasNext())
            {
                PlaneSelf PlaneSelf = iteratorPlaneSelf.next();
                double d = Math.pow(Math.abs(PlaneSelf.x - BulletSelf.x),2) + Math.pow(Math.abs(PlaneSelf.y - BulletSelf.y),2);
                //System.out.println("x^2 + y^2: " + d);
                if (d < 600)
                {
                    iteratorPlaneSelf.remove();
                }
            }
        }
    }

    void PlaneSelfsOperation(Vector<PlaneSelf> PlaneSelfs, Vector<BulletSelf> BulletSelfs)
    {
        Iterator<PlaneSelf> iterator = PlaneSelfs.iterator();
        while (iterator.hasNext())
        {
            PlaneSelf PlaneSelf = iterator.next();
            bufferGraphics.setColor(PlaneSelf.color);
            bufferGraphics.drawString(PlaneSelf.name, PlaneSelf.x, PlaneSelf.y); //画子弹
            if (PlaneSelf.type == 2)
                PlaneSelf.moveDown(); //子弹要移动，并且是自动移动，而飞机是通过方向键移动的

            if (timer % PlaneSelf.fireInterval == 0) {
                PlaneSelf.fire(BulletSelfs);
            }

            //如果超出窗口的边界，就要删除
            if (PlaneSelf.x < 0 || PlaneSelf.x > 700 || PlaneSelf.y < 0 || PlaneSelf.y > 900)
                iterator.remove();
        }
    }

    void updateWindow() {
        timer++;
        bufferGraphics.clearRect(0, 0, 700, 1000);

        PlaneSelfsOperation(friendPlaneSelfs, friendBulletSelfs);
        BulletSelfsOperation(friendBulletSelfs, bufferGraphics);

        //下边是敌方飞机处理
        if (timer % enemyAddInterval == 0) //timer每过一段时间，添加敌机
        {
            enemyCount++;
            enemyPlaneSelfs.add(new PlaneSelf((int) (100 + 500 * Math.random()), 0, 0, 10, "BulletSelf" + enemyCount, 2, 3, 15, new Color(255,0,0)));
        }

        PlaneSelfsOperation(enemyPlaneSelfs, enemyBulletSelfs);
        BulletSelfsOperation(enemyBulletSelfs, bufferGraphics);
        hit(enemyPlaneSelfs, friendBulletSelfs);

        graphics.drawImage(buffer, 0, 0, null);
    }

    public static void main(String[] args) throws InterruptedException {
        GameFrameSelf gameFrame = new GameFrameSelf() ;
        while (true) {
            gameFrame.updateWindow();
            Thread.sleep(70);
        }
    }
}